/*
 * v1.2 by  tonydon
 * netbeansIDE 7.1
 */
package cn.txdnet.txweb;

import cn.txdnet.txweb.annotation.methods.GetMethod;
import cn.txdnet.txweb.annotation.methods.PostMethod;
import cn.txdnet.txweb.model.ModelHandler;
import cn.txdnet.txweb.utils.SiteActionMgr;
import cn.txdnet.txweb.utils.WebUtil;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import txdnet.util.Logger;

/**
 * 这是一个简单的控制器,用于将匹配的url方法提交给对应的 action class并调用方法执行输出.
 *
 * @author txdnet
 */
public class Controller extends HttpServlet {

    private static final long serialVersionUID = 389288232965112901L;
    private static Class clazz = Controller.class;

    @Override
    public void init() {
        Logger.info(clazz, "Init TxWeb Controller.");
    }

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest req, HttpServletResponse res, boolean is_post_req) {
        String servletPath = req.getServletPath();
        String pathInfo = req.getPathInfo();
        String url = WebUtil.getRequestUrl(servletPath, pathInfo);
        String methodName = WebUtil.getUrlMethod(url);
        String urlaction = WebUtil.getUrlAction(url);
        try {

            if (methodName.length() == 0) {
                res.sendError(HttpServletResponse.SC_NOT_FOUND, "NOT_DEFINED_METHOD");
                return;
            }
            if (urlaction.equals(servletPath)) {
                res.sendError(HttpServletResponse.SC_NOT_FOUND, "NOT_FOUND_ACTION_PATH");
                return;
            }
            Object obj = SiteActionMgr.getAction(urlaction);
            if (obj == null) {
                throw new RuntimeException("Url Action Object Is Null. Url:".concat(urlaction));
            }
            
            Method m = SiteActionMgr.getMethod(obj, methodName);

            if (m == null) {
                throw new RuntimeException("Action Method Is Null. Call:".concat(methodName));
            }

            // GET POST请求检查
            if (is_post_req && m.isAnnotationPresent(GetMethod.class)) {
                throw new RuntimeException("Action Method Deny Post Request. Call:".concat(methodName));
            }
            if (!is_post_req && m.isAnnotationPresent(PostMethod.class)) {
                throw new RuntimeException("Action Method Deny Get Request. Call:".concat(methodName));
            }

            // 按照参数个数调用方法
            int arg_count = m.getParameterTypes().length;
            Object methodReturnObj = null;
            switch (arg_count) {
                case 0:
                    methodReturnObj = m.invoke(obj);
                    break;
                case 1:
                    methodReturnObj = m.invoke(obj, req);
                    break;
                case 2:
                    methodReturnObj = m.invoke(obj, req, res);
                    break;
                default:
                    res.sendError(HttpServletResponse.SC_NOT_FOUND, "NOT_MATCH_ACTION_METHOD.");
            }
            // 处理数据模型返回客户视图
            if (methodReturnObj != null) {
                ModelHandler.processor(methodReturnObj, req, res, urlaction);
            }
        } catch (Exception e) {
            Logger.error(clazz, e);
            try {
                res.sendError(HttpServletResponse.SC_BAD_REQUEST, e.toString());
            } catch (IOException ioe) {
                Logger.error(clazz, ioe.toString());
            }
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response, false);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response, true);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Txweb Action Controller Servlet.";
    }// </editor-fold>
}
